// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This file is part of CodingEditor.
// Note:	This project is derived from Peter Project
//			(hosted on sourceforge and codeplex)
//
// Copyright (c) 2008-2009, CE Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


namespace CE.Main
{
	using System;
	using System.IO;
	using System.Text.RegularExpressions;
	using System.Windows.Forms;

	using CE.API;

	using ICSharpCode.TextEditor;

	using WeifenLuo.WinFormsUI.Docking;

	public sealed partial class CodeStructure : DockContent, ICEPluginTab
	{
		#region Fields

		private bool m_CanScroll;
		private TextEditorControl m_Editor;

		#endregion Fields

		#region Constructors

		public CodeStructure()
		{
			InitializeComponent();
			m_CanScroll = true;
			TabText = "Code Structure";
			treeMain.AfterSelect += treeMain_AfterSelect;
			ToolStripManager.Renderer = new CE.CustomControls.Office2007Renderer();
		}

		#endregion Constructors

		#region Properties

		public bool AbleToCopy
		{
			get { return false; }
		}

		public bool AbleToCut
		{
			get { return false; }
		}

		public bool AbleToDelete
		{
			get { return false; }
		}

		public bool AbleToPaste
		{
			get { return false; }
		}

		public bool AbleToRedo
		{
			get { return false; }
		}

		public bool AbleToSave
		{
			get { return false; }
		}

		public bool AbleToSelectAll
		{
			get { return false; }
		}

		public bool AbleToUndo
		{
			get { return false; }
		}

		/// <summary>
		/// Gets or Sets if we are able to scroll to the selected item...
		/// </summary>
		public bool CanScroll
		{
			get { return m_CanScroll; }

			set { m_CanScroll = value; }
		}

		public string FileName
		{
			get { return ""; }
		}

		public ICEPluginHost Host
		{
			get;
			set;
		}

		/// <summary>
		/// Gets the number of Items in the TreeView...
		/// </summary>
		public int ItemCount
		{
			get { return treeMain.Nodes.Count; }
		}

		public bool NeedsSaving
		{
			get { return false; }
		}

		public string Selection
		{
			get { return ""; }
		}

		#endregion Properties

		#region Methods

		/// <summary>
		/// Occurs when the active content is changed...
		/// </summary>
		/// <param name="content">New Content</param>
		public void ActiveContentChanged(IDockContent content)
		{
			var d = (DockContent)content;
			TextEditorControl edit = null;
			foreach (Control c in d.Controls) {
				if (c.GetType().ToString().Equals(typeof(TextEditorControl).ToString())) {
					edit = (TextEditorControl)c;
					break;
				}
			}
			if (edit != m_Editor) {
				m_Editor = edit;
				ParseCode();
			}

			if (ItemCount == 0 && m_Editor != null) {
				ParseCode();
			}
		}

		/// <summary>
		/// Adds a node to the tree...
		/// </summary>
		/// <param name="node">Node to Add</param>
		public void AddNode(TreeNode node)
		{
			treeMain.Nodes.Add(node);
		}

		/// <summary>
		/// Clears the list view's items and groups...
		/// </summary>
		public void Clear() // Exception
		{
			if (treeMain.Nodes.Count > 0) treeMain.Nodes.Clear();
			//try
			//{
			//    treeMain.Nodes.Clear();
			//}
			//catch (Exception ex)
			//{
			//    MessageBox.Show(ex.Message + "\n" + ex.InnerException, "Coding Editor", MessageBoxButtons.OK,
			//                    MessageBoxIcon.Information);
			//}
		}

		public bool CloseTab()
		{
			Close();
			return true;
		}



		public bool FindNext(Regex reg, bool searchUp)
		{
			return false;
		}

		public void Copy()
		{
		}
		public void Cut()
		{
		}
		public void Delete()
		{
		}
		public void Duplicate()
		{
		}
		public void MarkAll(Regex reg)
		{
		}
		public void Paste()
		{
		}
		public void Print(bool showDialog)
		{
		}
		public void Redo()
		{
		}
		public void ReplaceAll(Regex reg, string replaceWith)
		{
		}
		public void ReplaceNext(Regex reg, string replaceWith, bool searchUp)
		{
		}
		public void Save()
		{
		}
		public void SaveAs(string filePath)
		{
		}
		public void SelectAll()
		{
		}
		public void SelectWord(int line, int offset, int wordLeng)
		{
		}

		/// <summary>
		/// Scrolls the active editor to the given offset...
		/// </summary>
		/// <param name="offset">offset to start at</param>
		/// <param name="pos">offset to end at</param>
		public void ScrollToOffset(int offset, int pos)
		{
			int line = m_Editor.Document.GetLineNumberForOffset(offset);
			m_Editor.ActiveTextAreaControl.Caret.Position = m_Editor.Document.OffsetToPosition(offset);
			m_Editor.ActiveTextAreaControl.SelectionManager.SetSelection(
			        m_Editor.Document.OffsetToPosition(offset), m_Editor.Document.OffsetToPosition(pos));
			m_Editor.ActiveTextAreaControl.CenterViewOn(line, 0);
			m_Editor.ActiveTextAreaControl.TextArea.Focus();
		}



		/// <summary>
		/// Sets the image list of the tree...
		/// </summary>
		/// <param name="fileExt">Image list name to set...</param>
		public void SetImageList(string fileExt)
		{
			switch (fileExt) {
			    case ".css":
				    treeMain.ImageList = imgCSS;
				    break;
			    case ".cs":
				    treeMain.ImageList = imgCS;
				    break;
			    default:
				    treeMain.ImageList = null;
				    break;
			}
		}

		/// <summary>
		/// Gets the Nodes for the tree...
		/// </summary>
		/// <returns>TreeNodeCollection</returns>
		public TreeNodeCollection TreeNodes()
		{
			return treeMain.Nodes;
		}

		public void Undo()
		{
		}

		private void CodeStructure_FormClosed(object sender, FormClosedEventArgs e)
		{
			Dispose(true);
		}

		private void ParseCode()
		{
			Clear();

			if (m_Editor != null) {
				if (!string.IsNullOrEmpty(m_Editor.FileName)) {
					string ext = Path.GetExtension(m_Editor.FileName).ToLower();
					SetImageList(ext);
					m_CanScroll = true;

					switch (ext) {
					    /*.manifest;.config;.addin;.wxs;.wxi;.wxl;.proj;
					     * .ilproj;.booproj;.build;.xfrm;.targets;
					     * .xpt;.xft;.map;.wsdl;.disco*/
					    case ".xml":
					    case ".xshd":
					    case ".csproj":
					    case ".vbproj":
					    case ".xaml":
					    case ".xsl":
					    case ".xslt":
					    case ".xsd":
					    case ".jpx":
					    case ".ceproj":
						    m_CanScroll = false;
						    CE.Parsers.Xml.XmlParser.ParseToTree(m_Editor.FileName, TreeNodes());
						    break;
					    case ".cs":
						    CE.Parsers.CS.CSParser.ParseToTree(m_Editor.FileName, TreeNodes());
						    break;
					    case ".css":
						    m_CanScroll = false;
						    CE.Parsers.CSS.CSSParser.ParseToTree(m_Editor.FileName, TreeNodes());
						    break;
					    case ".java":
						    CE.Parsers.Java.JavaParser.ParseToTree(m_Editor.FileName, TreeNodes());
						    break;
					    case ".c":
					    case ".h":
					    case ".cpp":
					    case ".cc":
					    case ".cxx":
					    case ".hpp":
						    CE.Parsers.C.CParser.ParseToTree(m_Editor.FileName, TreeNodes());
						    break;
					}
				}
			}
		}

		private void toolStripButton1_Click(object sender, EventArgs e)
		{
			ParseCode();
		}

		/// <summary>
		/// After an item is selected, scroll to it...
		/// </summary>
		/// <param name="sender">TreeView</param>
		/// <param name="e">TreeViewEventArgs</param>
		private void treeMain_AfterSelect(object sender, TreeViewEventArgs e)
		{
			if (tsbGotoCode.Checked) {
				if (m_CanScroll) {
					if (e.Node.Parent != null) {
						if (e.Node.Tag != null) {
							int off = Convert.ToInt32(e.Node.Tag.ToString());
							int index = e.Node.Text.IndexOf(":");
							int temp = e.Node.Text.IndexOf("(");
							if ((temp < index && temp > 0) || index == -1) {
								index = temp;
							}
							temp = e.Node.Text.IndexOf(" ");
							if ((temp < index && temp > 0) || index == -1) {
								index = temp;
							}
							int pos;
							if (index < 0) {
								pos = off + e.Node.Text.Length;
							} else {
								pos = off + index;
							}
							ScrollToOffset(off, pos);
						}
					}
				}
			}
		}

		private void tsbCollapseAll_Click(object sender, EventArgs e)
		{
			for (int a = 0; a < treeMain.Nodes.Count; a++) {
				treeMain.Nodes[a].Collapse();
			}
		}

		private void tsbExpandAll_Click(object sender, EventArgs e)
		{
			for (int a = 0; a < treeMain.Nodes.Count; a++) {
				treeMain.Nodes[a].ExpandAll();
			}
		}

		#endregion Methods
	}
}